home *** CD-ROM | disk | FTP | other *** search
/ MACD 5 / MACD 5.bin / workbench / libs / unixlib.lha / unix / src / sockets.c < prev    next >
C/C++ Source or Header  |  1996-10-23  |  9KB  |  381 lines

  1. #ifdef AMITCP
  2. #include "amiga.h"
  3. #include "files.h"
  4. #include <sys/ioctl.h>
  5. #include <sys/cdefs.h>
  6. #include <amiga/ioctl.h>
  7. #include <string.h>
  8. #include <netdb.h>
  9. #undef _OPTINLINE
  10. #include <proto/socket.h>
  11. #include <amitcp/socketbasetags.h>
  12. #include <intuition/intuition.h>
  13. #include <signal.h>
  14.  
  15. #undef lseek
  16. #undef read
  17. #undef write
  18. #undef close
  19.  
  20. extern void _message(char *format,...);
  21. long ASM fdCallback(REG(d0) int fd, REG(d1) int action);
  22.  
  23. struct Library *SocketBase = NULL;
  24. int h_errno = 0;
  25.  
  26. static long sigio_ok, sigurg_ok;
  27. extern long _sigio_sig, _sigurg_sig;
  28. extern long _fd_setsize;
  29.  
  30. long __stdargs
  31. _STI_200_openSockets(void)
  32. {
  33.     struct Library *msg_IntuitionBase;
  34.     LONG msg_req(struct Window *, struct EasyStruct *, ULONG *, APTR);
  35. #pragma libcall msg_IntuitionBase msg_req 24C BA9804
  36.     extern char *_ProgramName;
  37.  
  38.     if ((SocketBase = OpenLibrary("bsdsocket.library", 4)) != NULL) {
  39.     if (SocketBaseTags(SBTM_SETVAL(SBTC_ERRNOLONGPTR), &errno,
  40.                SBTM_SETVAL(SBTC_HERRNOLONGPTR), &h_errno,
  41.                SBTM_SETVAL(SBTC_LOGTAGPTR), _ProgramName,
  42.                SBTM_SETVAL(SBTC_DTABLESIZE), _fd_setsize,
  43.                TAG_END))
  44.         return 1;
  45.  
  46.     _sigio_sig = AllocSignal(-1);
  47.     sigio_ok = _sigio_sig >= 0 &&
  48.         !SocketBaseTags(SBTM_SETVAL(SBTC_SIGIOMASK), sigmask(_sigio_sig),
  49.             TAG_END);
  50.  
  51.     _sigurg_sig = AllocSignal(-1);
  52.     sigurg_ok = _sigurg_sig >= 0 &&
  53.         !SocketBaseTags(SBTM_SETVAL(SBTC_SIGURGMASK), sigmask(_sigurg_sig),
  54.             TAG_END);
  55.     return 0;
  56.     }
  57.     msg_IntuitionBase = OpenLibrary("intuition.library", 37);
  58.     if (msg_IntuitionBase) {
  59.     struct EasyStruct msg;
  60.     msg.es_StructSize = sizeof(msg);
  61.     msg.es_Flags = 0;
  62.     msg.es_Title = _ProgramName;
  63.     msg.es_TextFormat = "AmiTCP/IP version 4 or later is not running";
  64.     msg.es_GadgetFormat = "Exit %s";
  65.     msg_req(NULL, &msg, NULL, (APTR)&_ProgramName);
  66.     CloseLibrary(msg_IntuitionBase);
  67.     }
  68.     return 1;
  69. }
  70.  
  71. void __stdargs
  72. _STD_200_closeSockets(void)
  73. {
  74.     if (SocketBase) {
  75.     CloseLibrary(SocketBase);
  76.     SocketBase = NULL;
  77.     }
  78.     if (_sigio_sig >= 0)
  79.     FreeSignal(_sigio_sig);
  80.     if (_sigurg_sig >= 0)
  81.     FreeSignal(_sigurg_sig);
  82. }
  83.  
  84. long __stdargs
  85. _STI_510_install_AmiTCP_callback(void)
  86. {
  87.     if (SocketBaseTags(SBTM_SETVAL(SBTC_FDCALLBACK), &fdCallback, TAG_END)) {
  88.     _message("Cannot install fdCallback!");
  89.     return 1;
  90.     }
  91.     return 0;
  92. }
  93.  
  94. /* Code for fd's describing sockets */
  95.  
  96. struct sockinfo {
  97.     int fd;
  98. };
  99.  
  100. static ULONG sock_select_start(void *userinfo, int rd, int wr, int ex)
  101. {
  102.     int fd = ((struct sockinfo *)userinfo)->fd;
  103.  
  104.     if ((sigio_ok && (rd || wr)) || (sigurg_ok && ex)) {
  105.     int async = 1;
  106.     IoctlSocket(fd, FIOASYNC, (char *)&async);
  107.     }
  108.     return 0;
  109. }
  110.  
  111. static int sock_select_poll(void *userinfo, int *rd, int *wr, int *ex)
  112. {
  113.     int ret, async = 0;
  114.     int fd = ((struct sockinfo *)userinfo)->fd;
  115.     struct timeval timeout = {0, 0};
  116.     fd_set *rdfds = NULL, *wrfds = NULL, *exfds = NULL;
  117.  
  118.     IoctlSocket(fd, FIOASYNC, (char *)&async);
  119.  
  120.     if (*rd) {
  121.     if (!(rdfds = calloc(howmany(_fd_setsize, NFDBITS), sizeof(fd_mask))))
  122.         goto nomem;
  123.     FD_SET(fd, rdfds);
  124.     }
  125.     if (*wr) {
  126.     if (!(wrfds = calloc(howmany(_fd_setsize, NFDBITS), sizeof(fd_mask))))
  127.         goto nomem;
  128.     FD_SET(fd, wrfds);
  129.     }
  130.     if (*ex) {
  131.     if (!(exfds = calloc(howmany(_fd_setsize, NFDBITS), sizeof(fd_mask))))
  132.         goto nomem;
  133.     FD_SET(fd, exfds);
  134.     }
  135.  
  136.     ret = WaitSelect(fd+1, rdfds, wrfds, exfds, &timeout, NULL);
  137.  
  138.     if (*rd) {
  139.     *rd = FD_ISSET(fd, rdfds);
  140.     free(rdfds);
  141.     }
  142.     if (*wr) {
  143.     *wr = FD_ISSET(fd, wrfds);
  144.     free(wrfds);
  145.     }
  146.     if (*ex) {
  147.     *ex = FD_ISSET(fd, exfds);
  148.     free(exfds);
  149.     }
  150.  
  151.     return(ret);
  152.  
  153. nomem:
  154.     if (rdfds)
  155.     free(rdfds);
  156.     if (wrfds)
  157.     free(wrfds);
  158.     if (exfds)
  159.     free(exfds);
  160.     errno = ENOMEM;
  161.     return -1;
  162. }
  163.  
  164. static int sock_read(void *userinfo, void *buffer, unsigned int length)
  165. {
  166.     int fd = ((struct sockinfo *)userinfo)->fd;
  167.     int cnt;
  168.  
  169.     if ((cnt = recv(fd, (UBYTE *)buffer, length, 0)) < 0)
  170.     return -1;
  171.     return cnt;
  172. }
  173.  
  174. static int sock_write(void *userinfo, void *buffer, unsigned int length)
  175. {
  176.     int fd = ((struct sockinfo *)userinfo)->fd;
  177.     int cnt;
  178.  
  179.     if ((cnt = send(fd, (char *)buffer, length, 0)) < 0)
  180.     return -1;
  181.     return cnt;
  182. }
  183.  
  184. static int sock_lseek(void *userinfo, long rpos, int mode)
  185. {
  186.     errno = ESPIPE;
  187.     return -1;
  188. }
  189.  
  190. static int sock_close(void *userinfo, int internal)
  191. {
  192.     int fd = ((struct sockinfo *)userinfo)->fd;
  193.  
  194. #ifdef DEBUG
  195.     _message("Closing socket %ld, ptr=%ld", fd, userinfo);
  196. #endif
  197.     CloseSocket(fd);
  198.     /* This is not an error return, but is intended to
  199.      * signal __close() not to free the slot for the fd:
  200.      * this will be the job of fdCallback.
  201.      */
  202.     return 1;
  203. }
  204.  
  205. static int sock_ioctl(void *userinfo, int request, void *data)
  206. {
  207.     int fd = ((struct sockinfo *)userinfo)->fd;
  208.  
  209.     switch (request) {
  210.     case _AMIGA_INTERACTIVE:
  211.     case _AMIGA_GET_FH:
  212.     case _AMIGA_FREE_FH:
  213.     case _AMIGA_TRUNCATE:
  214.     case _AMIGA_SETPROTECTION:
  215.     case _AMIGA_DELETE_IF_ME:
  216.         errno = EINVAL;
  217.         return -1;
  218.     case _AMIGA_IS_FIFO: {
  219.         int *is_fifo = data;
  220.  
  221.         *is_fifo = FALSE;
  222.         return 0;
  223.     }
  224.     case _AMIGA_IS_SOCK: {
  225.         int *is_sock = data;
  226.  
  227.         *is_sock = TRUE;
  228.         return 0;
  229.     }
  230.     default:
  231.         return(IoctlSocket(fd, request, data));
  232.     }
  233. }
  234.  
  235. long ASM SAVEDS
  236. fdCallback(REG(d0) int fd, REG(d1) int action)
  237. {
  238.     struct fileinfo *fi;
  239.  
  240.     switch (action) {
  241.     case FDCB_FREE:
  242.         if (fi = _find_fd(fd)) {
  243.         int is_sock;
  244.         if (fi->ioctl(fi->userinfo, _AMIGA_IS_SOCK, &is_sock) == -1) {
  245. #ifdef DEBUG
  246.             _message("Requested to free fd %ld, but can't find it", fd);
  247. #endif
  248.             return EBADF;
  249.         }
  250.         if (!is_sock) {
  251. #ifdef DEBUG
  252.             _message("Requested to free fd %ld, but it isn't a socket", fd);
  253. #endif
  254.             return ENOTSOCK;
  255.         }
  256. #ifdef DEBUG
  257.         _message("Requested to free fd %ld, ptr=%ld", fd, fi->userinfo);
  258. #endif
  259.         free(fi->userinfo);
  260.         _free_fd(fd);
  261.         return 0;
  262.         }
  263.         return EBADF;
  264.     
  265.     case FDCB_ALLOC: {
  266.         int fd2;
  267.         struct fileinfo **fdtab;
  268.         struct sockinfo *new = malloc(sizeof(struct sockinfo));
  269. #ifdef DEBUG
  270.         _message("Requested to allocate fd %ld, ptr=%ld", fd, new);
  271. #endif
  272.         if (_get_free_fd(&fd2, &fdtab) < 0) {
  273.         free(new);
  274.         return ENOMEM;
  275.         }
  276.         /*
  277.          * If a file descriptor associated with a file or pipe was
  278.          * freed, the first free fd could be less than the minimum fd
  279.          * AmiTCP thinks is available. Because of this we must do ourself
  280.          * the job of _alloc_fd() which would allocate the lowest
  281.          * available fd. The only possibility that fd2 > fd is that
  282.          * the fd was allocated, by an open() or pipe() call for example,
  283.          * in the time between the check and allocation request by AmiTCP.
  284.          * Hopefully this is a low probability event.
  285.          */
  286.         if (fd2 != fd) {
  287.         int i, fdmax = _last_fd();
  288.         struct fileinfo *info;
  289. #ifdef DEBUG
  290.         if (fd2 > fd) {
  291.             _message("fdCallback: fd2(%ld) > fd(%ld)!", fd2, fd);
  292.             free(new);
  293.             return EINVAL;
  294.         }
  295. #endif
  296.         fdtab[fd2] = NULL;    /* free the slot for other uses */
  297.         info = (struct fileinfo *) &fdtab[fdmax];
  298.         for (i = 0; i < fdmax; i++) {
  299.             if (info[i].userinfo == 0) {
  300.             fdtab[fd] = info + i;    /* fd was already checked     */
  301.             break;            /* and should be free, unless */
  302.             }                /* fd2 > fd, in which case it */
  303.         }                /* is a disaster              */
  304.         }
  305.         new->fd = fd;
  306.         fdtab[fd]->userinfo = new;
  307.         fdtab[fd]->flags = FI_READ|FI_WRITE;
  308.         fdtab[fd]->count = 1;
  309.         fdtab[fd]->select_start = sock_select_start;
  310.         fdtab[fd]->select_poll = sock_select_poll;
  311.         fdtab[fd]->read = sock_read;
  312.         fdtab[fd]->write = sock_write;
  313.         fdtab[fd]->lseek = sock_lseek;
  314.         fdtab[fd]->close = sock_close;
  315.         fdtab[fd]->ioctl = sock_ioctl;
  316.         return 0;
  317.     }
  318.     case FDCB_CHECK:
  319. #ifdef DEBUG
  320.         _message("Requested to check fd %ld", fd);
  321. #endif
  322.         if (_find_fd(fd))
  323.         return EBADF;
  324.         return 0;
  325.  
  326.     default:
  327. #ifdef DEBUG
  328.         _message("fdCallback: invalid action.");
  329. #endif
  330.         return EINVAL;
  331.     }
  332. }
  333.  
  334. char * 
  335. inet_ntoa(struct in_addr addr) 
  336. {
  337.   return Inet_NtoA(addr.s_addr);
  338. }
  339.  
  340. struct in_addr 
  341. inet_makeaddr(int net, int host)
  342. {
  343.   struct in_addr addr;
  344.   addr.s_addr = Inet_MakeAddr(net, host);
  345.   return addr;
  346. }
  347.  
  348. unsigned long 
  349. inet_lnaof(struct in_addr addr) 
  350. {
  351.   return Inet_LnaOf(addr.s_addr);
  352. }
  353.  
  354. unsigned long   
  355. inet_netof(struct in_addr addr)
  356. {
  357.   return Inet_NetOf(addr.s_addr);
  358. }
  359.  
  360. struct hostent *gethostent(void)
  361. {
  362.     return NULL;
  363. }
  364.  
  365. struct netent *getnetent(void)
  366. {
  367.     return NULL;
  368. }
  369.  
  370. struct servent *getservent(void)
  371. {
  372.     return NULL;
  373. }
  374.  
  375. struct protoent *getprotoent(void)
  376. {
  377.     return NULL;
  378. }
  379.  
  380. #endif    /* AMITCP */
  381.